#include "llm_infer_native.h"
#include "napi/native_api.h"
#include <cstdint>
#include <string>

#include "llm_infer.h"
#include "utils_ndk.h"
#include <condition_variable>
#include <future>
#include <hilog/log.h>
#include <string>
#include <thread>

LLMInferHandle_t g_handle = NULL;
std::string CreatePrompt(const std::string &input_string) {
    return std::string("<|im_start|>system\nYou are a very helpful assistant.<|im_end|>\n<|im_start|>user\n" +
                       input_string + "<|im_end|>\n<|im_start|>assistant");
}

std::string CreateVideoSumaryPrompt(const std::string &input_string) {
    return std::string("<|im_start|>system\nYou are a very helpful "
                       "assistant.<|im_end|>\n<|im_start|>"
                       "user\n请基于下列用户观看的视频信息和行为信息，总结用户观看视频的兴趣，不超过30个字" +
                       input_string +
                       "<|im_end|>\n<"
                       "|im_start|>assistant");
}

static napi_value InitEnv(napi_env env, napi_callback_info info) {
    const char *generate_params =
        "scale_gp_size:128;max_length:1024;do_sample:true;num_beams:1;penalty_alpha:0.0;temperature:"
        "0.3;top_k:50;top_p:1.0;typical_p:1.0;diversity_penalty:0.0;repetition_penalty:"
        "1.0;length_penalty:1.0;random_seed:10;is_stream:false;system_string:system;model_path:;xx:;";
    const char *model_base_path = "/data/storage/el1/bundle/entry/resources/resfile/model/"
                                  "qwen2.5_0_5b_4bit_resource_g128";
    g_handle = LLMInfer_Native_Create();

    auto ret = LLMInfer_Native_Build(g_handle, model_base_path, generate_params, true);
    if (ret != 0) {
        LOGE("llmInfer Build failed. ret: %{public}d", ret);
        return nullptr;
    }
    LOGI("MindSpore Lite LLMInfer llmInfer Build success.");
    return nullptr;
}

static napi_value Destroy(napi_env env, napi_callback_info info) {
    if (g_handle != NULL) {
        LLMInfer_Native_Destroy(g_handle);
    }
    g_handle = NULL;
    return nullptr;
}

static napi_value GetWord(napi_env env, napi_callback_info info) {
    char *generated_word = NULL;
    bool *is_end = (bool *)malloc(sizeof(bool));
    int res = LLMInfer_Native_Stream_Word(g_handle, &generated_word, is_end);
    napi_value object;
    napi_create_object(env, &object);
    if (*is_end == 0) {
        napi_value res = nullptr;

        std::string res_word;
        if (generated_word == NULL) {
            res_word = "";
        } else {
            res_word = std::string(generated_word);
            delete[] generated_word; // 使用 delete[] 而不是 delete
            generated_word = NULL;
        }
        napi_create_string_utf8(env, res_word.c_str(), NAPI_AUTO_LENGTH, &res);
        napi_value property_name_out_string = nullptr;
        napi_create_string_utf8(env, "outputString", NAPI_AUTO_LENGTH, &property_name_out_string);
        napi_set_property(env, object, property_name_out_string, res);

        napi_value property_rescode = nullptr;
        napi_create_string_utf8(env, "resCode", NAPI_AUTO_LENGTH, &property_rescode);
        napi_value value = nullptr;
        napi_create_uint32(env, 1, &value);
        napi_set_property(env, object, property_rescode, value);
    } else {
        napi_value res = nullptr;
        napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &res);
        napi_value property_name_out_string = nullptr;
        napi_create_string_utf8(env, "outputString", NAPI_AUTO_LENGTH, &property_name_out_string);
        napi_set_property(env, object, property_name_out_string, res);

        napi_value property_rescode = nullptr;
        napi_create_string_utf8(env, "resCode", NAPI_AUTO_LENGTH, &property_rescode);
        napi_value value = nullptr;
        napi_create_uint32(env, 0, &value);
        napi_set_property(env, object, property_rescode, value);
    }
    free(is_end);
    return object;
}

// 3. 定义一个具体的回调函数
void my_callback(const char *result, void *user_data) { printf("Received result: %s\n", result); }

static napi_value StopGenerate(napi_env env, napi_callback_info info) {
    int res = LLMInfer_Native_Stop_Generate(g_handle);
    if(res != 0) {
        LOGI("stop generate failed.");
    }
    return nullptr;
}

static napi_value Run(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    char text[2048];
    size_t size = 2048;
    napi_get_value_string_utf8(env, args[0], text, 2048, &size);
    napi_value object = nullptr;
    napi_create_object(env, &object);
    std::string input_string(text);
    input_string = CreatePrompt(input_string);
    int res = LLMInfer_Native_Generate_Stream(g_handle, input_string.c_str());
    napi_value obj = nullptr;
    napi_create_uint32(env, res, &obj);
    return obj;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"run", nullptr, Run, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"init", nullptr, InitEnv, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"destroy", nullptr, Destroy, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getWord", nullptr, GetWord, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"stopGenerate", nullptr, StopGenerate, nullptr, nullptr, nullptr, napi_default, nullptr},
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
